package com.xzzz.irda.auth.core.exception;

import com.xzzz.common.base.BaseProperties;
import com.xzzz.common.base.enums.ExFormat;
import com.xzzz.common.base.enums.ExStackTrace;
import com.xzzz.common.base.pojo.IRCode;
import com.xzzz.common.base.pojo.R;
import com.xzzz.common.base.pojo.RCode;
import com.xzzz.common.base.util.ExceptionUtil;
import com.xzzz.common.base.util.ServletUtil;
import com.xzzz.common.base.util.json.JsonUtil;
import com.xzzz.common.base.util.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Optional;

/**
 * 拦截器的异常处理, 拦截器发生的错误需要显式的设置 response 中的响应体
 *
 * @author wangyf
 * 
 */
@Slf4j
public class DefaultAuthFailureHandler implements AuthFailureHandler {

    @Override
    public void onAuthenticationFailure(ServletRequest request, ServletResponse response, Exception exception) throws IOException {
        HttpServletResponse resp = (HttpServletResponse) response;

        resp.setContentType("application/json;charset=utf-8");
        // 要求所有响应都为 200
        resp.setStatus(200);
        PrintWriter out = resp.getWriter();

        // 自定义响应码
        IRCode authCode = RCode.INTERNAL_SERVER_ERROR;
        if (exception instanceof AuthException) {
            authCode = AuthRCode.getByCode(((AuthException) exception).getCode());
        }
        printStackTrace(authCode, exception);

        R<Object> apiResult = R.fault(
                authCode.getCode(),
                authCode.getMsg(),
                exception.getMessage());
        apiResult.setFrom("[IRDA-AUTH] DefaultAuthFailureHandler");

        String resultJson = JsonUtil.toJson(apiResult);
        out.write(resultJson);
        out.flush();
        out.close();
    }

    private void printStackTrace(IRCode authCode, Exception exception) {
        boolean filterStackTrace = false;
        boolean onLine = false;

        try {
            BaseProperties properties = SpringUtil.getBean(BaseProperties.class);
            filterStackTrace = properties.getEx().getStackTrace().equals(ExStackTrace.project);
            onLine = properties.getEx().getFormat().equals(ExFormat.line);
        } catch (Exception e) {
            e.printStackTrace();
        }

        log.error("{} | {}({})", ServletUtil.getUri(), exception.getClass().getSimpleName(),
                Optional.ofNullable(authCode.getMsg()).orElse(""));
        log.error(ExceptionUtil.printStackTrace(exception, filterStackTrace, onLine));
    }
}
